import mxgraph from './index';
import EditorUi from './EditorUi';
import {Menus} from './Menus';
import Editor from './Editor';

const {
  mxGraph,
  mxVertexHandler,
  mxConstants,
  mxCellState,
  mxPerimeter,
  mxCellEditor,
  mxGraphHandler,
  mxEvent,
  mxEdgeHandler,
  mxShape,
  mxConnectionConstraint,
  mxPoint,
  mxEventObject,
  mxCodec,
  mxObjectCodec,
  mxUtils,
  mxImageExport,
  mxXmlCanvas2D,
  mxCodecRegistry,
  mxResources,
  mxClient,
  mxPopupMenu,
} = mxgraph;

/**
 * Copyright (c) 2006-2012, JGraph Ltd
 */
/**
 * Construcs a new toolbar for the given editor.
 */
function Toolbar(editorUi, container) {
  this.editorUi = editorUi;
  this.container = container;
  this.staticElements = [];
  this.init();

  // Global handler to hide the current menu
  this.gestureHandler = mxUtils.bind(this, function (evt) {
    if (this.editorUi.currentMenu != null && mxEvent.getSource(evt) != this.editorUi.currentMenu.div) {
      this.hideMenu();
    }
  });

  mxEvent.addGestureListeners(document, this.gestureHandler);
};

/**
 * Image for the dropdown arrow.
 */
Toolbar.prototype.dropdownImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/dropdown.gif' : '';

/**
 * Image element for the dropdown arrow.
 */
Toolbar.prototype.dropdownImageHtml = '<img border="0" style="position:absolute;right:4px;top:' +
  ((!EditorUi.compactUi) ? 8 : 6) + 'px;" src="' + Toolbar.prototype.dropdownImage + '" valign="middle"/>';

/**
 * Defines the background for selected buttons.
 */
Toolbar.prototype.selectedBackground = '#d0d0d0';

/**
 * Defines the background for selected buttons.
 */
Toolbar.prototype.unselectedBackground = 'none';

/**
 * Array that contains the DOM nodes that should never be removed.
 */
Toolbar.prototype.staticElements = null;

/**
 * Adds the toolbar elements.
 * 导航栏的标签
 */
Toolbar.prototype.init = function () {
  var sw = screen.width;
  // Takes into account initial compact mode
  sw -= (screen.height > 740) ? 56 : 0;
  // console.log("sw:",sw);
  if (sw >= 700) {

    //返回列表
    this.addItems(['backToList', '-']);


    //返回上一级菜单//暂时不用
    // var backMenu = this.addMenu('', mxResources.get('back'), true, 'back', null, true);
    // this.addDropDownArrow(backMenu, 'geSprite-back', 50, 50, -6, -3, 36, -8);
    // this.addSeparator();

    // 文件
    var fileMenu = this.addMenu('', mxResources.get('file'), true, 'file', null, true);
    this.addDropDownArrow(fileMenu, 'geSprite-file', 50, 50, -6, -3, 36, -8);
    //图片导航的每个菜单的宽度，(width - 10)
    //this.addDropDownArrow():里面对应的传值 menu, sprite, width, atlasWidth, left, top, atlasDelta, atlasLeft
    this.addSeparator();

    //编辑
    var editMenu = this.addMenu('', mxResources.get('edit'), true, 'edit', null, true);
    this.addDropDownArrow(editMenu, 'geSprite-edit', 50, 50, -6, -3, 36, -8);
    this.addSeparator();

    //视图(全局)
    var globalViewMenu = this.addMenu('', mxResources.get('view'), true, 'view', null, true);
    this.addDropDownArrow(globalViewMenu, 'geSprite-view', 50, 50, -6, -3, 36, -8);
    this.addSeparator();

    //布局
    var layoutMenu = this.addMenu('', mxResources.get('arrange'), true, 'arrange', null, true);
    this.addDropDownArrow(layoutMenu, 'geSprite-layout', 50, 50, -6, -3, 36, -8);
    this.addSeparator();

    //其他
    var otherMenu = this.addMenu('', mxResources.get('extras'), true, 'extras', null, true);
    this.addDropDownArrow(otherMenu, 'geSprite-other', 50, 50, -6, -3, 36, -8);
    this.addSeparator();

    //自动保存文字提示
    // var saveMenu = this.addMenu('autosave', mxResources.get('autosave'), true, 'autosave', null, true);
    // this.addDropDownArrow(saveMenu, 'geSprite-save', 50, 50, -6, -3, 36, -8);
    // this.addSeparator();

    //精灵图视图
    var formatMenu = this.addMenu('', mxResources.get('view') + ' (' + mxResources.get('panTooltip') + ')', true, 'viewPanels', null, true);
    this.addDropDownArrow(formatMenu, 'geSprite-formatpanel', 50, 50, -6, -3, 36, -8);
    this.addSeparator();
  }
  var viewMenu = this.addMenu('', mxResources.get('zoom') + ' (Alt+鼠标滚轮)', true, 'viewZoom', null, true);
  viewMenu.showDisabled = true;
  viewMenu.style.whiteSpace = 'nowrap';
  viewMenu.style.position = 'relative';
  viewMenu.style.overflow = 'hidden';

  if (EditorUi.compactUi) {
    viewMenu.style.width = (mxClient.IS_QUIRKS) ? '58px' : '60px'; //缩放的样式
  } else {
    viewMenu.style.width = (mxClient.IS_QUIRKS) ? '62px' : '36px';
  }

  if (sw >= 420) {
    this.addSeparator();
    //放大, 缩小
    var elts = this.addItems(['zoomIn', 'zoomOut']);
    elts[0].setAttribute('title', mxResources.get('zoomIn') + ' (' + this.editorUi.actions.get('zoomIn').shortcut + ')');
    elts[1].setAttribute('title', mxResources.get('zoomOut') + ' (' + this.editorUi.actions.get('zoomOut').shortcut + ')');
  }

  // Updates the label if the scale changes
  this.updateZoom = mxUtils.bind(this, function () {
    viewMenu.innerHTML = Math.round(this.editorUi.editor.graph.view.scale * 100) + '%' +
      this.dropdownImageHtml;
    if (EditorUi.compactUi) {
      viewMenu.getElementsByTagName('img')[0].style.right = '1px';
      viewMenu.getElementsByTagName('img')[0].style.top = '5px';
    }
  });

  this.editorUi.editor.graph.view.addListener(mxEvent.EVENT_SCALE, this.updateZoom);
  this.editorUi.editor.addListener('resetGraphView', this.updateZoom);
  //撤销，重做
  var elts = this.addItems(['-', 'undo', 'redo']);
  elts[1].setAttribute('title', mxResources.get('undo') + ' (' + this.editorUi.actions.get('undo').shortcut + ')');
  elts[2].setAttribute('title', mxResources.get('redo') + ' (' + this.editorUi.actions.get('redo').shortcut + ')');

  if (sw >= 320) {
    //删除
    var elts = this.addItems(['-', 'delete']);
    elts[1].setAttribute('title', mxResources.get('delete') + ' (' + this.editorUi.actions.get('delete').shortcut + ')');
  }

  if (sw >= 550) {
    //置于顶层，置于底层
    this.addItems(['-', 'toFront', 'toBack']);
  }

  if (sw >= 740) {
    //填充色
    this.addItems(['-', 'fillColor']);
    if (sw >= 780) {
      //线条颜色
      this.addItems(['strokeColor']);
      if (sw >= 820) {
        //阴影
        this.addItems(['shadow']);
      }
    }
  }

  if (sw >= 400) {
    this.addSeparator();
    if (sw >= 440) {
      //连接
      this.edgeShapeMenu = this.addMenuFunction('', mxResources.get('connection'), false, mxUtils.bind(this, function (menu) {
        this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], [null, null], 'geIcon geSprite geSprite-connection', null, true).setAttribute('title', mxResources.get('line'));
        this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['link', null], 'geIcon geSprite geSprite-linkedge', null, true).setAttribute('title', mxResources.get('link'));
        this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['flexArrow', null], 'geIcon geSprite geSprite-arrow', null, true).setAttribute('title', mxResources.get('arrow'));
        this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['arrow', null], 'geIcon geSprite geSprite-simplearrow', null, true).setAttribute('title', mxResources.get('simpleArrow'));
      }));

      this.addDropDownArrow(this.edgeShapeMenu, 'geSprite-connection', 50, 50, 0, 0, 22, -4);
    }
    //锚点
    this.edgeStyleMenu = this.addMenuFunction('geSprite-orthogonal', mxResources.get('waypoints'), false, mxUtils.bind(this, function (menu) {
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], [null, null, null], 'geIcon geSprite geSprite-straight', null, true).setAttribute('title', mxResources.get('straight'));
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', null, null], 'geIcon geSprite geSprite-orthogonal', null, true).setAttribute('title', mxResources.get('orthogonal'));
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalelbow', null, true).setAttribute('title', mxResources.get('simple'));
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalelbow', null, true).setAttribute('title', mxResources.get('simple'));
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalisometric', null, true).setAttribute('title', mxResources.get('isometric'));
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalisometric', null, true).setAttribute('title', mxResources.get('isometric'));
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', '1', null], 'geIcon geSprite geSprite-curved', null, true).setAttribute('title', mxResources.get('curved'));
      this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['entityRelationEdgeStyle', null, null], 'geIcon geSprite geSprite-entity', null, true).setAttribute('title', mxResources.get('entityRelation'));
    }));

    this.addDropDownArrow(this.edgeStyleMenu, 'geSprite-orthogonal', 50, 50, 0, 0, 22, -4);
  }

  this.addSeparator();
  //插入
  var insertMenu = this.addMenu('', mxResources.get('insert') + ' (' + mxResources.get('doubleClickTooltip') + ')', true, 'insert', null, true);
  this.addDropDownArrow(insertMenu, 'geSprite-plus', 50, 50, -4, -3, 36, -8);
  
  //导航栏加入table
  this.addTableDropDown();

  //自动绘制布局
  this.addItems(['-', 'autoDraw', '-',]);

  //图例: 图例获取、图例保存按钮 
  var legendMenu = this.addMenu('', mxResources.get('legendOperation'), true, 'legendOperation', null, true);
  this.addDropDownArrow(legendMenu, 'geSprite-legend', 50, 50, -6, -3, 36, -8);
  this.addSeparator();

  //保存Topo图
  this.addItems(['saveTopo', '-',]);

};

/**
 * Adds the toolbar elements.
 */
Toolbar.prototype.addTableDropDown = function () {
  this.addSeparator();

	// KNOWN: All table stuff does not work with undo/redo
	// KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems
	// to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text).
	var menuElt = this.addMenuFunction('geIcon geSprite geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function (menu) {
		var graph = this.editorUi.editor.graph;
		var cell = graph.getSelectionCell();

		if (!graph.isTableCell(cell) && !graph.isTableRow(cell) && !graph.isTable(cell)) {
			this.editorUi.menus.addInsertTableCellItem(menu);
		} else {
			var elt = menu.addItem('', null, mxUtils.bind(this, function () {
				try {
					graph.insertTableColumn(cell, true);
				} catch (e) {
					this.editorUi.handleError(e);
				}
			}), null, 'geIcon geSprite geSprite-insertcolumnbefore');
			elt.setAttribute('title', mxResources.get('insertColumnBefore'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.insertTableColumn(cell, false);
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-insertcolumnafter');
      elt.setAttribute('title', mxResources.get('insertColumnAfter'));

      elt = menu.addItem('Delete column', null, mxUtils.bind(this, function () {
        if (cell != null) {
          try {
            graph.deleteTableColumn(cell);
          } catch (e) {
            this.editorUi.handleError(e);
          }
        }
      }), null, 'geIcon geSprite geSprite-deletecolumn');
      elt.setAttribute('title', mxResources.get('deleteColumn'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.insertTableRow(cell, true);
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-insertrowbefore');
      elt.setAttribute('title', mxResources.get('insertRowBefore'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.insertTableRow(cell, false);
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-insertrowafter');
      elt.setAttribute('title', mxResources.get('insertRowAfter'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.deleteTableRow(cell);
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-deleterow');
      elt.setAttribute('title', mxResources.get('deleteRow'));
    }
  }));

	menuElt.style.position = 'relative';
	menuElt.style.whiteSpace = 'nowrap';
	menuElt.style.overflow = 'hidden';
	menuElt.innerHTML = '<div class="geSprite geSprite-table" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
	menuElt.style.width = (mxClient.IS_QUIRKS) ? '50px' : '40px'; //修改表格最外层的宽度

	// Fix for item size in kennedy theme
	if (EditorUi.compactUi) {
		menuElt.getElementsByTagName('img')[0].style.left = '22px';
		menuElt.getElementsByTagName('img')[0].style.top = '5px';
	}

	// Connects to insert menu enabled state
	var menu = this.editorUi.menus.get('insert');

	// Workaround for possible not a function
	// when extending HTML objects
	if (menu != null && typeof menuElt.setEnabled === 'function') {
		menu.addListener('stateChanged', function () {
			menuElt.setEnabled(menu.enabled);
		});
	}

	return menuElt;
};

/**
 * Adds the toolbar elements.
 */
Toolbar.prototype.addDropDownArrow = function (menu, sprite, width, atlasWidth, left, top, atlasDelta, atlasLeft) {
  atlasDelta = (atlasDelta != null) ? atlasDelta : 32;
  left = (EditorUi.compactUi) ? left : atlasLeft;

  menu.style.whiteSpace = 'nowrap';
  menu.style.overflow = 'hidden';
  menu.style.position = 'relative';
  menu.innerHTML = '<div class="geSprite ' + sprite + '" style="margin-left:' + left + 'px;margin-top:' + top + 'px;"></div>' +
    this.dropdownImageHtml;
  menu.style.width = (mxClient.IS_QUIRKS) ? atlasWidth + 'px' : (atlasWidth - atlasDelta) + 'px';

  if (mxClient.IS_QUIRKS) {
    menu.style.height = (EditorUi.compactUi) ? '24px' : '26px';
  }

  // Fix for item size in kennedy theme
  if (EditorUi.compactUi) {
    menu.getElementsByTagName('img')[0].style.left = '28px'; // 图片右边 连接和锚点后面的三角
    menu.getElementsByTagName('img')[0].style.top = '5px';
    menu.style.width = (mxClient.IS_QUIRKS) ? width + 'px' : (width - 10) + 'px';
  }
};

/**
 * Sets the current font name.
 */
Toolbar.prototype.setFontName = function (value) {
  if (this.fontMenu != null) {
    this.fontMenu.innerHTML = '<div style="width:60px;overflow:hidden;display:inline-block;">' +
      mxUtils.htmlEntities(value) + '</div>' + this.dropdownImageHtml;
  }
};

/**
 * Sets the current font name.
 */
Toolbar.prototype.setFontSize = function (value) {
  if (this.sizeMenu != null) {
    this.sizeMenu.innerHTML = '<div style="width:24px;overflow:hidden;display:inline-block;">' +
      value + '</div>' + this.dropdownImageHtml;
  }
};

/**
 * Hides the current menu.
 * 画布是 table 导航栏的菜单
 */
Toolbar.prototype.createTextToolbar = function () {
  var graph = this.editorUi.editor.graph;

  var styleElt = this.addMenu('', mxResources.get('style'), true, 'formatBlock');
  styleElt.style.position = 'relative';
  styleElt.style.whiteSpace = 'nowrap';
  styleElt.style.overflow = 'hidden';
  styleElt.innerHTML = mxResources.get('style') + this.dropdownImageHtml;

  if (EditorUi.compactUi) {
    styleElt.style.paddingRight = '18px';
    styleElt.getElementsByTagName('img')[0].style.right = '1px';
    styleElt.getElementsByTagName('img')[0].style.top = '5px';
  }

  this.addSeparator();
  //画布内容是表格  导航字体类型
  this.fontMenu = this.addMenu('', mxResources.get('fontFamily'), true, 'fontFamily');
  this.fontMenu.style.position = 'relative';
  this.fontMenu.style.whiteSpace = 'nowrap';
  this.fontMenu.style.overflow = 'hidden';
  this.fontMenu.style.width = (mxClient.IS_QUIRKS) ? '100px' : '90px'; //

  this.setFontName(Menus.prototype.defaultFont);

  if (EditorUi.compactUi) {
    this.fontMenu.style.paddingRight = '18px';
    this.fontMenu.getElementsByTagName('img')[0].style.right = '1px';
    this.fontMenu.getElementsByTagName('img')[0].style.top = '5px';
  }

  this.addSeparator();
  //画布内容是表格  导航字体大小
  this.sizeMenu = this.addMenu(Menus.prototype.defaultFontSize, mxResources.get('fontSize'), true, 'fontSize');
  this.sizeMenu.style.position = 'relative';
  this.sizeMenu.style.whiteSpace = 'nowrap';
  this.sizeMenu.style.overflow = 'hidden';
  this.sizeMenu.style.width = (mxClient.IS_QUIRKS) ? '50px' : '48px'; //

  this.setFontSize(Menus.prototype.defaultFontSize);

  if (EditorUi.compactUi) {
    this.sizeMenu.style.paddingRight = '18px';
    this.sizeMenu.getElementsByTagName('img')[0].style.right = '1px';
    this.sizeMenu.getElementsByTagName('img')[0].style.top = '5px';
  }

  var elts = this.addItems(['-', 'undo', 'redo', '-', 'bold', 'italic', 'underline']);
  elts[1].setAttribute('title', mxResources.get('undo') + ' (' + this.editorUi.actions.get('undo').shortcut + ')');
  elts[2].setAttribute('title', mxResources.get('redo') + ' (' + this.editorUi.actions.get('redo').shortcut + ')');
  elts[4].setAttribute('title', mxResources.get('bold') + ' (' + this.editorUi.actions.get('bold').shortcut + ')');
  elts[5].setAttribute('title', mxResources.get('italic') + ' (' + this.editorUi.actions.get('italic').shortcut + ')');
  elts[6].setAttribute('title', mxResources.get('underline') + ' (' + this.editorUi.actions.get('underline').shortcut + ')');

  // KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems
  // to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text).
  var alignMenu = this.addMenuFunction('', mxResources.get('align'), false, mxUtils.bind(this, function (menu) {
    elt = menu.addItem('', null, mxUtils.bind(this, function (evt) {
      graph.cellEditor.alignText(mxConstants.ALIGN_LEFT, evt);
    }), null, 'geIcon geSprite geSprite-left');
    elt.setAttribute('title', mxResources.get('left'));

    elt = menu.addItem('', null, mxUtils.bind(this, function (evt) {
      graph.cellEditor.alignText(mxConstants.ALIGN_CENTER, evt);
    }), null, 'geIcon geSprite geSprite-center');
    elt.setAttribute('title', mxResources.get('center'));

    elt = menu.addItem('', null, mxUtils.bind(this, function (evt) {
      graph.cellEditor.alignText(mxConstants.ALIGN_RIGHT, evt);
    }), null, 'geIcon geSprite geSprite-right');
    elt.setAttribute('title', mxResources.get('right'));

    elt = menu.addItem('', null, mxUtils.bind(this, function () {
      document.execCommand('justifyfull', false, null);
    }), null, 'geIcon geSprite geSprite-justifyfull');
    elt.setAttribute('title', mxResources.get('justifyfull'));

    elt = menu.addItem('', null, mxUtils.bind(this, function () {
      document.execCommand('insertorderedlist', false, null);
    }), null, 'geIcon geSprite geSprite-orderedlist');
    elt.setAttribute('title', mxResources.get('numberedList'));

    elt = menu.addItem('', null, mxUtils.bind(this, function () {
      document.execCommand('insertunorderedlist', false, null);
    }), null, 'geIcon geSprite geSprite-unorderedlist');
    elt.setAttribute('title', mxResources.get('bulletedList'));

    elt = menu.addItem('', null, mxUtils.bind(this, function () {
      document.execCommand('outdent', false, null);
    }), null, 'geIcon geSprite geSprite-outdent');
    elt.setAttribute('title', mxResources.get('decreaseIndent'));

    elt = menu.addItem('', null, mxUtils.bind(this, function () {
      document.execCommand('indent', false, null);
    }), null, 'geIcon geSprite geSprite-indent');
    elt.setAttribute('title', mxResources.get('increaseIndent'));
  }));

  alignMenu.style.position = 'relative';
  alignMenu.style.whiteSpace = 'nowrap';
  alignMenu.style.overflow = 'hidden';
  alignMenu.innerHTML = '<div class="geSprite geSprite-left" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
  alignMenu.style.width = (mxClient.IS_QUIRKS) ? '50px' : '38px'; //对齐的样式

  if (EditorUi.compactUi) {
    alignMenu.getElementsByTagName('img')[0].style.left = '22px';
    alignMenu.getElementsByTagName('img')[0].style.top = '5px';
  }

  var formatMenu = this.addMenuFunction('', mxResources.get('format'), false, mxUtils.bind(this, function (menu) {
    //下标
    elt = menu.addItem('', null, this.editorUi.actions.get('subscript').funct,
      null, 'geIcon geSprite geSprite-subscript');
    elt.setAttribute('title', mxResources.get('subscript') + ' (' + Editor.ctrlKey + '+,)');
    //上标
    elt = menu.addItem('', null, this.editorUi.actions.get('superscript').funct,
      null, 'geIcon geSprite geSprite-superscript');
    elt.setAttribute('title', mxResources.get('superscript') + ' (' + Editor.ctrlKey + '+.)');

    // KNOWN: IE+FF don't return keyboard focus after color dialog (calling focus doesn't help)
    elt = menu.addItem('', null, this.editorUi.actions.get('fontColor').funct,
      null, 'geIcon geSprite geSprite-fontcolor');
    elt.setAttribute('title', mxResources.get('fontColor'));

    elt = menu.addItem('', null, this.editorUi.actions.get('backgroundColor').funct,
      null, 'geIcon geSprite geSprite-fontbackground');
    elt.setAttribute('title', mxResources.get('backgroundColor'));

    elt = menu.addItem('', null, mxUtils.bind(this, function () {
      document.execCommand('removeformat', false, null);
    }), null, 'geIcon geSprite geSprite-removeformat');
    elt.setAttribute('title', mxResources.get('removeFormat'));
  }));

  formatMenu.style.position = 'relative';
  formatMenu.style.whiteSpace = 'nowrap';
  formatMenu.style.overflow = 'hidden';
  formatMenu.innerHTML = '<div class="geSprite geSprite-dots" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
  formatMenu.style.width = (mxClient.IS_QUIRKS) ? '58px' : '36px';

  if (EditorUi.compactUi) {
    formatMenu.getElementsByTagName('img')[0].style.left = '22px';
    formatMenu.getElementsByTagName('img')[0].style.top = '5px';
  }

  this.addSeparator();

  this.addButton('geIcon geSprite geSprite-code', mxResources.get('html'), function () {
    graph.cellEditor.toggleViewMode();

    if (graph.cellEditor.textarea.innerHTML.length > 0 && (graph.cellEditor.textarea.innerHTML != '&nbsp;' || !graph.cellEditor.clearOnChange)) {
      window.setTimeout(function () {
        document.execCommand('selectAll', false, null);
      });
    }
  });

  this.addSeparator();

  // FIXME: Uses geButton here and geLabel in main menu
  var insertMenu = this.addMenuFunction('', mxResources.get('insert'), true, mxUtils.bind(this, function (menu) {
    
    //插入链接
    menu.addItem(mxResources.get('insertLink'), null, mxUtils.bind(this, function () {
      this.editorUi.actions.get('link').funct();
    }));

    //插入图片
    menu.addItem(mxResources.get('insertImage'), null, mxUtils.bind(this, function () {
      this.editorUi.actions.get('image').funct();
    }));

    //插入水平标尺
    menu.addItem(mxResources.get('insertHorizontalRule'), null, mxUtils.bind(this, function () {
      document.execCommand('inserthorizontalrule', false, null);
    }));

  }));

  insertMenu.style.whiteSpace = 'nowrap';
  insertMenu.style.overflow = 'hidden';
  insertMenu.style.position = 'relative';
  insertMenu.innerHTML = '<div class="geSprite geSprite-plus" style="margin-left:-4px;margin-top:-3px;"></div>' +
    this.dropdownImageHtml;
  insertMenu.style.width = (mxClient.IS_QUIRKS) ? '36px' : '16px';

  // Fix for item size in kennedy theme
  if (EditorUi.compactUi) {
    insertMenu.getElementsByTagName('img')[0].style.left = '24px';
    insertMenu.getElementsByTagName('img')[0].style.top = '5px';
    insertMenu.style.width = (mxClient.IS_QUIRKS) ? '50px' : '40px'; // 插入的样式
  }

  this.addSeparator();

  // KNOWN: All table stuff does not work with undo/redo
  // KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems
  // to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text).
  //表格
  var elt = this.addMenuFunction('geIcon geSprite geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function (menu) {
    var elt = graph.getSelectedElement();
    var cell = graph.getParentByNames(elt, ['TD', 'TH'], graph.cellEditor.text2);
    var row = graph.getParentByName(elt, 'TR', graph.cellEditor.text2);

    if (row == null) {

      function createTable(rows, cols) {
        var html = ['<table>'];
        for (var i = 0; i < rows; i++) {
          html.push('<tr>');
          for (var j = 0; j < cols; j++) {
            html.push('<td><br></td>');
          }
          html.push('</tr>');
        }
        html.push('</table>');
        return html.join('');
      };

      this.editorUi.menus.addInsertTableItem(menu);
    } else {
      var table = graph.getParentByName(row, 'TABLE', graph.cellEditor.text2);

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.selectNode(graph.insertColumn(table, (cell != null) ? cell.cellIndex : 0));
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-insertcolumnbefore');
      elt.setAttribute('title', mxResources.get('insertColumnBefore'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.selectNode(graph.insertColumn(table, (cell != null) ? cell.cellIndex + 1 : -1));
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-insertcolumnafter');
      elt.setAttribute('title', mxResources.get('insertColumnAfter'));

      elt = menu.addItem('Delete column', null, mxUtils.bind(this, function () {
        if (cell != null) {
          try {
            graph.deleteColumn(table, cell.cellIndex);
          } catch (e) {
            this.editorUi.handleError(e);
          }
        }
      }), null, 'geIcon geSprite geSprite-deletecolumn');
      elt.setAttribute('title', mxResources.get('deleteColumn'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.selectNode(graph.insertRow(table, row.sectionRowIndex));
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-insertrowbefore');
      elt.setAttribute('title', mxResources.get('insertRowBefore'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.selectNode(graph.insertRow(table, row.sectionRowIndex + 1));
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-insertrowafter');
      elt.setAttribute('title', mxResources.get('insertRowAfter'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        try {
          graph.deleteRow(table, row.sectionRowIndex);
        } catch (e) {
          this.editorUi.handleError(e);
        }
      }), null, 'geIcon geSprite geSprite-deleterow');
      elt.setAttribute('title', mxResources.get('deleteRow'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        // Converts rgb(r,g,b) values
        var color = table.style.borderColor.replace(
          /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
          function ($0, $1, $2, $3) {
            return "#" + ("0" + Number($1).toString(16)).substr(-2) + ("0" + Number($2).toString(16)).substr(-2) + ("0" + Number($3).toString(16)).substr(-2);
          });
        this.editorUi.pickColor(color, function (newColor) {
          if (newColor == null || newColor == mxConstants.NONE) {
            table.removeAttribute('border');
            table.style.border = '';
            table.style.borderCollapse = '';
          } else {
            table.setAttribute('border', '1');
            table.style.border = '1px solid ' + newColor;
            table.style.borderCollapse = 'collapse';
          }
        });
      }), null, 'geIcon geSprite geSprite-strokecolor');
      elt.setAttribute('title', mxResources.get('borderColor'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        // Converts rgb(r,g,b) values
        var color = table.style.backgroundColor.replace(
          /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
          function ($0, $1, $2, $3) {
            return "#" + ("0" + Number($1).toString(16)).substr(-2) + ("0" + Number($2).toString(16)).substr(-2) + ("0" + Number($3).toString(16)).substr(-2);
          });
        this.editorUi.pickColor(color, function (newColor) {
          if (newColor == null || newColor == mxConstants.NONE) {
            table.style.backgroundColor = '';
          } else {
            table.style.backgroundColor = newColor;
          }
        });
      }), null, 'geIcon geSprite geSprite-fillcolor');
      elt.setAttribute('title', mxResources.get('backgroundColor'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        var value = table.getAttribute('cellPadding') || 0;

        var dlg = new FilenameDialog(this.editorUi, value, mxResources.get('apply'), mxUtils.bind(this, function (newValue) {
          if (newValue != null && newValue.length > 0) {
            table.setAttribute('cellPadding', newValue);
          } else {
            table.removeAttribute('cellPadding');
          }
        }), mxResources.get('spacing'));
        this.editorUi.showDialog(dlg.container, 300, 80, true, true);
        dlg.init();
      }), null, 'geIcon geSprite geSprite-fit');
      elt.setAttribute('title', mxResources.get('spacing'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        table.setAttribute('align', 'left');
      }), null, 'geIcon geSprite geSprite-left');
      elt.setAttribute('title', mxResources.get('left'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        table.setAttribute('align', 'center');
      }), null, 'geIcon geSprite geSprite-center');
      elt.setAttribute('title', mxResources.get('center'));

      elt = menu.addItem('', null, mxUtils.bind(this, function () {
        table.setAttribute('align', 'right');
      }), null, 'geIcon geSprite geSprite-right');
      elt.setAttribute('title', mxResources.get('right'));
    }
  }));

  elt.style.position = 'relative';
  elt.style.whiteSpace = 'nowrap';
  elt.style.overflow = 'hidden';
  elt.innerHTML = '<div class="geSprite geSprite-table" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
  elt.style.width = (mxClient.IS_QUIRKS) ? '50px' : '38px';

  // Fix for item size in kennedy theme
  if (EditorUi.compactUi) {
    elt.getElementsByTagName('img')[0].style.left = '22px';
    elt.getElementsByTagName('img')[0].style.top = '5px';
  }
};

/**
 * Hides the current menu.
 */
Toolbar.prototype.hideMenu = function () {
  this.editorUi.hideCurrentMenu();
};

/**
 * Adds a label to the toolbar.
 */
Toolbar.prototype.addMenu = function (label, tooltip, showLabels, name, c, showAll, ignoreState) {
  var menu = this.editorUi.menus.get(name);
  var elt = this.addMenuFunction(label, tooltip, showLabels, function () {
    menu.funct.apply(menu, arguments);
  }, c, showAll);

	// Workaround for possible not a function
	// when extending HTML objects
	if (!ignoreState && typeof elt.setEnabled === 'function') {
		menu.addListener('stateChanged', function () {
			elt.setEnabled(menu.enabled);
		});
	}

	return elt;
};

/**
 * Adds a label to the toolbar.
 */
Toolbar.prototype.addMenuFunction = function (label, tooltip, showLabels, funct, c, showAll) {
  return this.addMenuFunctionInContainer((c != null) ? c : this.container, label, tooltip, showLabels, funct, showAll);
};

/**
 * Adds a label to the toolbar.
 */
Toolbar.prototype.addMenuFunctionInContainer = function (container, label, tooltip, showLabels, funct, showAll) {
  var elt = (showLabels) ? this.createLabel(label) : this.createButton(label);
  this.initElement(elt, tooltip);
  this.addMenuHandler(elt, showLabels, funct, showAll);
  container.appendChild(elt);
  return elt;
};

/**
 * Adds a separator to the separator.
 */
Toolbar.prototype.addSeparator = function (c) {
  c = (c != null) ? c : this.container;
  var elt = document.createElement('div');
  elt.className = 'geSeparator';
  c.appendChild(elt);
  return elt;
};

/**
 * Adds given action item
 */
Toolbar.prototype.addItems = function (keys, c, ignoreDisabled) {
  var items = [];
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];

    if (key == '-') {
      items.push(this.addSeparator(c));
    } else {
      items.push(this.addItem('geSprite-' + key.toLowerCase(), key, c, ignoreDisabled));
    }
  }
  return items;
};

/**
 * Adds given action item
 */
Toolbar.prototype.addItem = function (sprite, key, c, ignoreDisabled) {
  var action = this.editorUi.actions.get(key);
  var elt = null;

  if (action != null) {
    var tooltip = action.label;

    if (action.shortcut != null) {
      tooltip += ' (' + action.shortcut + ')';
    }

    elt = this.addButton(sprite, tooltip, action.funct, c);

		// Workaround for possible not a function
		// when extending HTML objects
		if (!ignoreDisabled && typeof elt.setEnabled === 'function') {
			elt.setEnabled(action.enabled);

      action.addListener('stateChanged', function () {
        elt.setEnabled(action.enabled);
      });
    }
  }
  return elt;
};

/**
 * Adds a button to the toolbar.
 */
Toolbar.prototype.addButton = function (classname, tooltip, funct, c) {
  var elt = this.createButton(classname);
  c = (c != null) ? c : this.container;

  this.initElement(elt, tooltip);
  this.addClickHandler(elt, funct);
  c.appendChild(elt);
  return elt;
};

/**
 * Initializes the given toolbar element.
 */
Toolbar.prototype.initElement = function (elt, tooltip) {
  // Adds tooltip
  if (tooltip != null) {
    elt.setAttribute('title', tooltip);
  }
  this.addEnabledState(elt);
};

/**
 * Adds enabled state with setter to DOM node (avoids JS wrapper).
 */
Toolbar.prototype.addEnabledState = function (elt) {
  var classname = elt.className;

  elt.setEnabled = function (value) {
    elt.enabled = value;
    if (value) {
      elt.className = classname;
    } else {
      elt.className = classname + ' mxDisabled';
    }
  };
  elt.setEnabled(true);
};

/**
 * Adds enabled state with setter to DOM node (avoids JS wrapper).
 */
Toolbar.prototype.addClickHandler = function (elt, funct) {
  if (funct != null) {
    mxEvent.addListener(elt, 'click', function (evt) {
      if (elt.enabled) {
        funct(evt);
      }
      mxEvent.consume(evt);
    });
    // Prevents focus
    mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
      mxUtils.bind(this, function (evt) {
        evt.preventDefault();
      }));
  }
};

/**
 * Creates and returns a new button.
 */
Toolbar.prototype.createButton = function (classname) {
  var elt = document.createElement('a');
  elt.className = 'geButton';
  var inner = document.createElement('div');
  if (classname != null) {
    inner.className = 'geSprite ' + classname;
  }
  elt.appendChild(inner);
  return elt;
};

/**
 * Creates and returns a new button.
 */
Toolbar.prototype.createLabel = function (label, tooltip) {
  var elt = document.createElement('a');
  elt.className = 'geLabel';
  mxUtils.write(elt, label);
  return elt;
};

/**
 * Adds a handler for showing a menu in the given element.
 */
Toolbar.prototype.addMenuHandler = function (elt, showLabels, funct, showAll) {
  if (funct != null) {
    var graph = this.editorUi.editor.graph;
    var menu = null;
    var show = true;

    mxEvent.addListener(elt, 'click', mxUtils.bind(this, function (evt) {
      if (show && (elt.enabled == null || elt.enabled)) {
        graph.popupMenuHandler.hideMenu();
        menu = new mxPopupMenu(funct);
        menu.div.className += ' geToolbarMenu';
        menu.showDisabled = showAll;
        menu.labels = showLabels;
        menu.autoExpand = true;

        var offset = mxUtils.getOffset(elt);
        menu.popup(offset.x, offset.y + elt.offsetHeight, null, evt);
        this.editorUi.setCurrentMenu(menu, elt);
        // Workaround for scrollbar hiding menu items
        // console.log("geToolbarMenu:", !showLabels, menu.div.scrollHeight , menu.div.clientHeight);
        if (!showLabels && menu.div.scrollHeight > menu.div.clientHeight) {
          menu.div.style.width = '40px';
        }

        menu.hideMenu = mxUtils.bind(this, function () {
          mxPopupMenu.prototype.hideMenu.apply(menu, arguments);
          this.editorUi.resetCurrentMenu();
          menu.destroy();
        });

        // Extends destroy to reset global state
        menu.addListener(mxEvent.EVENT_HIDE, mxUtils.bind(this, function () {
          this.currentElt = null;
        }));
      }
      show = true;
      mxEvent.consume(evt);
    }));

    // Hides menu if already showing and prevents focus
    mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
      mxUtils.bind(this, function (evt) {
        show = this.currentElt != elt;
        evt.preventDefault();
      }));
  }
};

/**
 * Adds a handler for showing a menu in the given element.
 */
Toolbar.prototype.destroy = function () {
  if (this.gestureHandler != null) {
    mxEvent.removeGestureListeners(document, this.gestureHandler);
    this.gestureHandler = null;
  }
};

export default Toolbar;